package org.spider.spiderweb.logback;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.FileAppender;
import ch.qos.logback.core.spi.DeferredProcessingAware;
import org.spider.api.context.SpiderContext;
import org.spider.api.context.SpiderContextHolder;
import org.spider.core.job.SpiderJobContext;

import java.io.IOException;
import java.io.OutputStream;

/**
 * 自定义的fileAppender可以用自己指定的outputStream<br>
 * 很神奇，subAppend的执行线程是当前调用log的线程，不一定是main线程<br>
 * 还有一点，fileAppender类是线程安全的。但是那个线程安全的writeBytes方法是privately，要在该类写一份,
 * 此处因为是多线程环境，使用lock
 */

public class FileLogBackAppender extends FileAppender<ILoggingEvent> {
    @Override
    protected void subAppend(ILoggingEvent event) {
        OutputStream os = getOutputStream();
        // 查看环境类是否有OutputStream
        SpiderContext context = SpiderContextHolder.get();
        //只有spiderContext出现时才会输出日志到文件，其他情况不会输出
        if(context instanceof SpiderJobContext){
            os = ((SpiderJobContext)context).getOutputstream();
//            System.out.println("==file=appender======================");
        }
        try {
            // 父类源码-不用管
            if (event instanceof DeferredProcessingAware) {
                ((DeferredProcessingAware)event).prepareForDeferredProcessing();
            }
            byte[] bytes=this.encoder.encode(event);
            this.writeBytes(os,bytes);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    private void writeBytes(OutputStream os, byte[] byteArray) throws IOException {
        if (byteArray == null || byteArray.length == 0)
            return;
        // 防止写错误
        lock.lock();
        try {
            os.write(byteArray);
            if (isImmediateFlush()) {
                os.flush();
            }
        } finally {
            lock.unlock();
        }
    }
}
